import argparse
import secrets
import string
import sys
from pathlib import Path

# 让脚本可从项目根目录加载包（common、app 等）
PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

from common.config import settings
from common.logger import create_logger
from common.database import DatabaseManager
from app.common.security import hash_password


logger = create_logger(
    name="reset_password",
    log_level=settings.log_level,
    log_file=settings.log_file,
    enable_file_logging=settings.enable_file_logging,
)


def generate_strong_password(length: int = 14) -> str:
    """生成包含大小写、数字、特殊字符的强密码"""
    if length < 8:
        length = 8

    alphabet_lower = string.ascii_lowercase
    alphabet_upper = string.ascii_uppercase
    digits = string.digits
    specials = "!@#$%^&*()-_=+[]{}|;:,.<>?"

    # 保证至少包含每类字符
    base = [
        secrets.choice(alphabet_lower),
        secrets.choice(alphabet_upper),
        secrets.choice(digits),
        secrets.choice(specials),
    ]

    all_chars = alphabet_lower + alphabet_upper + digits + specials
    remaining = [secrets.choice(all_chars) for _ in range(length - len(base))]

    password_chars = base + remaining
    secrets.SystemRandom().shuffle(password_chars)
    return "".join(password_chars)


def reset_user_password(user_code: str, new_plain: str | None = None) -> str:
    """
    重置指定用户的密码：生成或使用传入的明文，写入哈希，并返回明文。

    会在控制台与日志输出明文密码（仅用于管理员操作，谨慎使用）。
    """
    if not user_code or not isinstance(user_code, str):
        raise ValueError("user_code 必须是非空字符串")

    plain = new_plain or generate_strong_password()
    hashed = hash_password(plain)

    sql = "UPDATE base_user SET hashed_password = %s WHERE user_code = %s"

    db = DatabaseManager()
    try:
        affected = db.execute_query(sql, params=(hashed, user_code), commit=True)
        if affected == 0:
            raise RuntimeError(f"未找到 user_code={user_code} 的用户")

        # 输出到日志与控制台（仅管理员场景，慎用）
        logger.info("用户 %s 已重置密码，新的明文密码为: %s", user_code, plain)
        print(f"用户 {user_code} 新密码(明文): {plain}")
        return plain
    except Exception as e:
        logger.error("重置密码失败: %s", e)
        raise


def main():
    parser = argparse.ArgumentParser(description="管理员重置用户密码并输出明文")
    parser.add_argument("user_code", help="base_user.user_code，例如 U20250912000003")
    parser.add_argument(
        "--password",
        dest="password",
        help="可选：指定新的明文密码；不提供则自动生成强密码",
    )
    args = parser.parse_args()

    reset_user_password(user_code=args.user_code, new_plain=args.password)


if __name__ == "__main__":
    main()